﻿using System;
using System.Collections.Generic;
using UnityEngine;

// Token: 0x02000148 RID: 328
[DisallowMultipleComponent]
[AddComponentMenu("RVP/C#/Suspension/Suspension", 0)]
[RequireComponent(typeof(DriveForce))]
[ExecuteInEditMode]
public class Suspension : MonoBehaviour
{
	// Token: 0x060005E9 RID: 1513 RVA: 0x0002F460 File Offset: 0x0002D660
	private void Start()
	{
		this.tr = base.transform;
		this.rb = (Rigidbody)F.GetTopmostParentComponent<Rigidbody>(this.tr);
		this.vp = (VehicleParent)F.GetTopmostParentComponent<VehicleParent>(this.tr);
		this.targetDrive = base.GetComponent<DriveForce>();
		this.flippedSide = (Vector3.Dot(this.tr.forward, this.vp.transform.right) < 0f);
		this.flippedSideFactor = (float)((!this.flippedSide) ? 1 : -1);
		this.initialRotation = this.tr.localRotation;
		if (Application.isPlaying)
		{
			this.GetCamber();
			if (this.generateHardCollider)
			{
				GameObject gameObject = new GameObject("Compress Collider");
				gameObject.layer = GlobalControl.ignoreWheelCastLayer;
				this.compressTr = gameObject.transform;
				this.compressTr.parent = this.tr;
				this.compressTr.localPosition = Vector3.zero;
				this.compressTr.localEulerAngles = new Vector3(this.camberAngle, 0f, -this.casterAngle * this.flippedSideFactor);
				this.compressCol = gameObject.AddComponent<CapsuleCollider>();
				this.compressCol.direction = 1;
				this.setHardColliderRadiusFactor = this.hardColliderRadiusFactor;
				this.hardColliderRadiusFactorPrev = this.setHardColliderRadiusFactor;
				this.compressCol.radius = this.wheel.rimWidth * this.hardColliderRadiusFactor;
				this.compressCol.height = ((!this.wheel.popped) ? Mathf.Lerp(this.wheel.rimRadius, this.wheel.tireRadius, this.wheel.tirePressure) : this.wheel.rimRadius) * 2f;
				this.compressCol.material = GlobalControl.frictionlessMatStatic;
			}
			this.steerRangeMax = Mathf.Max(this.steerRangeMin, this.steerRangeMax);
			this.properties = base.GetComponent<SuspensionPropertyToggle>();
			if (this.properties)
			{
				this.UpdateProperties();
			}
		}
	}

	// Token: 0x060005EA RID: 1514 RVA: 0x0002F67C File Offset: 0x0002D87C
	private void FixedUpdate()
	{
		this.upDir = this.tr.up;
		this.forwardDir = this.tr.forward;
		this.targetCompression = 1f;
		this.GetCamber();
		this.GetSpringVectors();
		if (this.wheel.connected)
		{
			this.compression = Mathf.Min(this.targetCompression, (this.suspensionDistance <= 0f) ? 0f : Mathf.Clamp01(this.wheel.contactPoint.distance / this.suspensionDistance));
			this.penetration = Mathf.Min(0f, this.wheel.contactPoint.distance);
		}
		else
		{
			this.compression = this.detachedCompression;
			this.penetration = 0f;
		}
		if (this.targetCompression > 0f)
		{
			this.ApplySuspensionForce();
		}
		if (this.generateHardCollider)
		{
			this.setHardColliderRadiusFactor = this.hardColliderRadiusFactor;
			if (this.hardColliderRadiusFactorPrev != this.setHardColliderRadiusFactor || this.wheel.updatedSize || this.wheel.updatedPopped)
			{
				if (this.wheel.rimWidth > this.wheel.actualRadius)
				{
					this.compressCol.direction = 2;
					this.compressCol.radius = this.wheel.actualRadius * this.hardColliderRadiusFactor;
					this.compressCol.height = this.wheel.rimWidth * 2f;
				}
				else
				{
					this.compressCol.direction = 1;
					this.compressCol.radius = this.wheel.rimWidth * this.hardColliderRadiusFactor;
					this.compressCol.height = this.wheel.actualRadius * 2f;
				}
			}
			this.hardColliderRadiusFactorPrev = this.setHardColliderRadiusFactor;
		}
		if (this.wheel.connected)
		{
			if (this.wheel.targetDrive)
			{
				this.targetDrive.active = this.driveEnabled;
				this.targetDrive.feedbackRPM = this.wheel.targetDrive.feedbackRPM;
				this.wheel.targetDrive.SetDrive(this.targetDrive);
			}
		}
		else
		{
			this.targetDrive.feedbackRPM = this.targetDrive.rpm;
		}
	}

	// Token: 0x060005EB RID: 1515 RVA: 0x0002F8EC File Offset: 0x0002DAEC
	private void Update()
	{
		this.GetCamber();
		if (!Application.isPlaying)
		{
			this.GetSpringVectors();
		}
		this.steerDegrees = Mathf.Abs(this.steerAngle) * ((this.steerAngle <= 0f) ? this.steerRangeMin : this.steerRangeMax);
	}

	// Token: 0x060005EC RID: 1516 RVA: 0x0002F944 File Offset: 0x0002DB44
	private void ApplySuspensionForce()
	{
		if (this.wheel.grounded && this.wheel.connected)
		{
			float z = this.vp.norm.InverseTransformDirection(this.rb.GetPointVelocity(this.tr.position)).z;
			if (this.suspensionDistance > 0f && this.targetCompression > 0f)
			{
				Vector3 vector = ((!this.leaningForce) ? this.vp.norm.forward : Vector3.Lerp(this.upDir, this.vp.norm.forward, Mathf.Abs(Mathf.Pow(Vector3.Dot(this.vp.norm.forward, this.vp.upDir), 5f)))) * this.springForce * (Mathf.Pow(this.springForceCurve.Evaluate(1f - this.compression), Mathf.Max(1f, this.springExponent)) - (1f - this.targetCompression) - this.springDampening * Mathf.Clamp(z, -1f, 1f));
				this.rb.AddForceAtPosition(vector, (!this.applyForceAtGroundContact) ? this.wheel.tr.position : this.wheel.contactPoint.point, ForceMode.Acceleration);
				if (this.wheel.contactPoint.col.attachedRigidbody)
				{
					this.wheel.contactPoint.col.attachedRigidbody.AddForceAtPosition(-vector, this.wheel.contactPoint.point, ForceMode.Acceleration);
				}
			}
			if (this.compression == 0f && !this.generateHardCollider && this.applyHardContactForce)
			{
				this.rb.AddForceAtPosition(-this.vp.norm.TransformDirection(0f, 0f, Mathf.Clamp(z, -this.hardContactSensitivity * TimeMaster.fixedTimeFactor, 0f) + this.penetration) * this.hardContactForce * Mathf.Clamp01(TimeMaster.fixedTimeFactor), (!this.applyForceAtGroundContact) ? this.wheel.tr.position : this.wheel.contactPoint.point, ForceMode.Acceleration);
			}
		}
	}

	// Token: 0x060005ED RID: 1517 RVA: 0x0002FBD4 File Offset: 0x0002DDD4
	private void GetSpringVectors()
	{
		if (!Application.isPlaying)
		{
			this.tr = base.transform;
			this.flippedSide = (Vector3.Dot(this.tr.forward, this.vp.transform.right) < 0f);
			this.flippedSideFactor = (float)((!this.flippedSide) ? 1 : -1);
		}
		this.maxCompressPoint = this.tr.position;
		float num = -Mathf.Sin(this.casterAngle * 0.017453292f) * this.flippedSideFactor;
		float num2 = -Mathf.Sin(this.sideAngle * 0.017453292f);
		this.springDirection = this.tr.TransformDirection(num, Mathf.Max(Mathf.Abs(num), Mathf.Abs(num2)) - 1f, num2).normalized;
	}

	// Token: 0x060005EE RID: 1518 RVA: 0x0002FCB0 File Offset: 0x0002DEB0
	private void GetCamber()
	{
		if (this.solidAxleCamber && this.oppositeWheel && this.wheel.connected)
		{
			if (this.oppositeWheel.wheel.rim && this.wheel.rim)
			{
				Vector3 vector = this.tr.InverseTransformDirection((this.oppositeWheel.wheel.rim.position - this.wheel.rim.position).normalized);
				this.camberAngle = Mathf.Atan2(vector.z, vector.y) * 57.29578f + 90f + this.camberOffset;
			}
		}
		else
		{
			this.camberAngle = this.camberCurve.Evaluate((!Application.isPlaying || !this.wheel.connected) ? this.targetCompression : this.wheel.travelDist) + this.camberOffset;
		}
	}

	// Token: 0x060005EF RID: 1519 RVA: 0x0002FDD0 File Offset: 0x0002DFD0
	public void UpdateProperties()
	{
		if (this.properties)
		{
			foreach (SuspensionToggledProperty suspensionToggledProperty in this.properties.properties)
			{
				switch (suspensionToggledProperty.property)
				{
				case SuspensionToggledProperty.Properties.steerEnable:
					this.steerEnabled = suspensionToggledProperty.toggled;
					break;
				case SuspensionToggledProperty.Properties.steerInvert:
					this.steerInverted = suspensionToggledProperty.toggled;
					break;
				case SuspensionToggledProperty.Properties.driveEnable:
					this.driveEnabled = suspensionToggledProperty.toggled;
					break;
				case SuspensionToggledProperty.Properties.driveInvert:
					this.driveInverted = suspensionToggledProperty.toggled;
					break;
				case SuspensionToggledProperty.Properties.ebrakeEnable:
					this.ebrakeEnabled = suspensionToggledProperty.toggled;
					break;
				case SuspensionToggledProperty.Properties.skidSteerBrake:
					this.skidSteerBrake = suspensionToggledProperty.toggled;
					break;
				}
			}
		}
	}

	// Token: 0x060005F0 RID: 1520 RVA: 0x0002FEA4 File Offset: 0x0002E0A4
	private void OnDrawGizmosSelected()
	{
		if (!this.tr)
		{
			this.tr = base.transform;
		}
		if (this.wheel && this.wheel.rim)
		{
			Vector3 position = this.wheel.rim.position;
			float num = -Mathf.Sin(this.camberAngle * 0.017453292f);
			float num2 = Mathf.Sin(Mathf.Lerp(this.steerRangeMin, this.steerRangeMax, (this.steerAngle + 1f) * 0.5f) * 0.017453292f);
			float num3 = Mathf.Sin(this.steerRangeMin * 0.017453292f);
			float num4 = Mathf.Sin(this.steerRangeMax * 0.017453292f);
			Gizmos.color = Color.magenta;
			Gizmos.DrawWireSphere(position, 0.05f);
			Gizmos.DrawLine(position, position + this.tr.TransformDirection(num3, num * (1f - Mathf.Abs(num3)), Mathf.Cos(this.steerRangeMin * 0.017453292f) * (1f - Mathf.Abs(num))).normalized);
			Gizmos.DrawLine(position, position + this.tr.TransformDirection(num4, num * (1f - Mathf.Abs(num4)), Mathf.Cos(this.steerRangeMax * 0.017453292f) * (1f - Mathf.Abs(num))).normalized);
			Gizmos.DrawLine(position + this.tr.TransformDirection(num3, num * (1f - Mathf.Abs(num3)), Mathf.Cos(this.steerRangeMin * 0.017453292f) * (1f - Mathf.Abs(num))).normalized * 0.9f, position + this.tr.TransformDirection(num4, num * (1f - Mathf.Abs(num4)), Mathf.Cos(this.steerRangeMax * 0.017453292f) * (1f - Mathf.Abs(num))).normalized * 0.9f);
			Gizmos.DrawLine(position, position + this.tr.TransformDirection(num2, num * (1f - Mathf.Abs(num2)), Mathf.Cos(this.steerRangeMin * 0.017453292f) * (1f - Mathf.Abs(num))).normalized);
		}
		Gizmos.color = Color.red;
		Gizmos.DrawWireSphere(this.tr.TransformPoint(this.damagePivot), 0.05f);
	}

	// Token: 0x040008DA RID: 2266
	[NonSerialized]
	public Transform tr;

	// Token: 0x040008DB RID: 2267
	private Rigidbody rb;

	// Token: 0x040008DC RID: 2268
	private VehicleParent vp;

	// Token: 0x040008DD RID: 2269
	[NonSerialized]
	public bool flippedSide;

	// Token: 0x040008DE RID: 2270
	[NonSerialized]
	public float flippedSideFactor;

	// Token: 0x040008DF RID: 2271
	[NonSerialized]
	public Quaternion initialRotation;

	// Token: 0x040008E0 RID: 2272
	public Wheel wheel;

	// Token: 0x040008E1 RID: 2273
	private CapsuleCollider compressCol;

	// Token: 0x040008E2 RID: 2274
	[Tooltip("Generate a capsule collider for hard compressions")]
	public bool generateHardCollider = true;

	// Token: 0x040008E3 RID: 2275
	[Tooltip("Multiplier for the radius of the hard collider")]
	public float hardColliderRadiusFactor = 1f;

	// Token: 0x040008E4 RID: 2276
	private float hardColliderRadiusFactorPrev;

	// Token: 0x040008E5 RID: 2277
	private float setHardColliderRadiusFactor;

	// Token: 0x040008E6 RID: 2278
	private Transform compressTr;

	// Token: 0x040008E7 RID: 2279
	[Header("Brakes and Steering")]
	public float brakeForce;

	// Token: 0x040008E8 RID: 2280
	public float ebrakeForce;

	// Token: 0x040008E9 RID: 2281
	[Range(-180f, 180f)]
	public float steerRangeMin;

	// Token: 0x040008EA RID: 2282
	[Range(-180f, 180f)]
	public float steerRangeMax;

	// Token: 0x040008EB RID: 2283
	[Tooltip("How much the wheel is steered")]
	public float steerFactor = 1f;

	// Token: 0x040008EC RID: 2284
	[Range(-1f, 1f)]
	public float steerAngle;

	// Token: 0x040008ED RID: 2285
	[NonSerialized]
	public float steerDegrees;

	// Token: 0x040008EE RID: 2286
	[Tooltip("Effect of Ackermann steering geometry")]
	public float ackermannFactor;

	// Token: 0x040008EF RID: 2287
	[Tooltip("The camber of the wheel as it travels, x-axis = compression, y-axis = angle")]
	public AnimationCurve camberCurve = AnimationCurve.Linear(0f, 0f, 1f, 0f);

	// Token: 0x040008F0 RID: 2288
	[Range(-89.999f, 89.999f)]
	public float camberOffset;

	// Token: 0x040008F1 RID: 2289
	[NonSerialized]
	public float camberAngle;

	// Token: 0x040008F2 RID: 2290
	[Tooltip("Adjust the camber as if it was connected to a solid axle, opposite wheel must be set")]
	public bool solidAxleCamber;

	// Token: 0x040008F3 RID: 2291
	public Suspension oppositeWheel;

	// Token: 0x040008F4 RID: 2292
	[Range(-89.999f, 89.999f)]
	[Tooltip("Angle at which the suspension points out to the side")]
	public float sideAngle;

	// Token: 0x040008F5 RID: 2293
	[Range(-89.999f, 89.999f)]
	public float casterAngle;

	// Token: 0x040008F6 RID: 2294
	[Range(-89.999f, 89.999f)]
	public float toeAngle;

	// Token: 0x040008F7 RID: 2295
	[Tooltip("Wheel offset from its pivot point")]
	public float pivotOffset;

	// Token: 0x040008F8 RID: 2296
	[NonSerialized]
	public List<SuspensionPart> movingParts = new List<SuspensionPart>();

	// Token: 0x040008F9 RID: 2297
	[Header("Spring")]
	public float suspensionDistance;

	// Token: 0x040008FA RID: 2298
	[NonSerialized]
	public float compression;

	// Token: 0x040008FB RID: 2299
	[Tooltip("Should be left at 1 unless testing suspension travel")]
	[Range(0f, 1f)]
	public float targetCompression;

	// Token: 0x040008FC RID: 2300
	[NonSerialized]
	public float penetration;

	// Token: 0x040008FD RID: 2301
	public float springForce;

	// Token: 0x040008FE RID: 2302
	[Tooltip("Force of the curve depending on it's compression, x-axis = compression, y-axis = force")]
	public AnimationCurve springForceCurve = AnimationCurve.Linear(0f, 0f, 1f, 1f);

	// Token: 0x040008FF RID: 2303
	[Tooltip("Exponent for spring force based on compression")]
	public float springExponent = 1f;

	// Token: 0x04000900 RID: 2304
	public float springDampening;

	// Token: 0x04000901 RID: 2305
	[Tooltip("How quickly the suspension extends if it's not grounded")]
	public float extendSpeed = 20f;

	// Token: 0x04000902 RID: 2306
	[Tooltip("Apply forces to prevent the wheel from intersecting with the ground, not necessary if generating a hard collider")]
	public bool applyHardContactForce = true;

	// Token: 0x04000903 RID: 2307
	public float hardContactForce = 50f;

	// Token: 0x04000904 RID: 2308
	public float hardContactSensitivity = 2f;

	// Token: 0x04000905 RID: 2309
	[Tooltip("Apply suspension forces at ground point")]
	public bool applyForceAtGroundContact = true;

	// Token: 0x04000906 RID: 2310
	[Tooltip("Apply suspension forces along local up direction instead of ground normal")]
	public bool leaningForce;

	// Token: 0x04000907 RID: 2311
	[NonSerialized]
	public Vector3 maxCompressPoint;

	// Token: 0x04000908 RID: 2312
	[NonSerialized]
	public Vector3 springDirection;

	// Token: 0x04000909 RID: 2313
	[NonSerialized]
	public Vector3 upDir;

	// Token: 0x0400090A RID: 2314
	[NonSerialized]
	public Vector3 forwardDir;

	// Token: 0x0400090B RID: 2315
	[NonSerialized]
	public DriveForce targetDrive;

	// Token: 0x0400090C RID: 2316
	[NonSerialized]
	public SuspensionPropertyToggle properties;

	// Token: 0x0400090D RID: 2317
	[NonSerialized]
	public bool steerEnabled = true;

	// Token: 0x0400090E RID: 2318
	[NonSerialized]
	public bool steerInverted;

	// Token: 0x0400090F RID: 2319
	[NonSerialized]
	public bool driveEnabled = true;

	// Token: 0x04000910 RID: 2320
	[NonSerialized]
	public bool driveInverted;

	// Token: 0x04000911 RID: 2321
	[NonSerialized]
	public bool ebrakeEnabled = true;

	// Token: 0x04000912 RID: 2322
	[NonSerialized]
	public bool skidSteerBrake;

	// Token: 0x04000913 RID: 2323
	[Tooltip("Point around which the suspension pivots when damaged")]
	[Header("Damage")]
	public Vector3 damagePivot;

	// Token: 0x04000914 RID: 2324
	[Tooltip("Compression amount to remain at when wheel is detached")]
	[Range(0f, 1f)]
	public float detachedCompression = 0.5f;

	// Token: 0x04000915 RID: 2325
	public float jamForce = float.PositiveInfinity;

	// Token: 0x04000916 RID: 2326
	[NonSerialized]
	public bool jammed;
}
